package cn.iocoder.yudao.module.member.service.praxisEntryInfo;

import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.EmailInfo;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.member.controller.admin.praxisEntryInfo.vo.*;
import cn.iocoder.yudao.module.member.controller.admin.praxisProject.vo.PraxisProjectScheduleVO;
import cn.iocoder.yudao.module.member.dal.dataobject.praxisEntryChosen.PraxisEntryChosenDO;
import cn.iocoder.yudao.module.member.dal.dataobject.praxisEntryInfo.PraxisEntryInfoDO;
import cn.iocoder.yudao.module.member.dal.mysql.praxisEntryChosen.PraxisEntryChosenMapper;
import cn.iocoder.yudao.module.member.dal.mysql.praxisEntryInfo.PraxisEntryInfoMapper;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;

/**
 * 项目报名信息 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class PraxisEntryInfoServiceImpl implements PraxisEntryInfoService {

    @Resource
    private PraxisEntryInfoMapper praxisEntryInfoMapper;
    @Resource
    private PraxisEntryChosenMapper praxisEntryChosenMapper;

    @Value("${spring.profiles.active}")
    private String active;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;


    @Override
    public PageResult<PraxisEntryInfoPageRespVO> getEntryInfoPage(PraxisEntryInfoPageReqVO pageReqVO) {
        // MyBatis Plus 查询
        IPage<PraxisEntryInfoPageRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        if(StringUtils.isNotBlank(pageReqVO.getTitle())){
            params.put("title",pageReqVO.getTitle());
        }
        if(null!=pageReqVO.getScheduleType()){
            params.put("scheduleType",pageReqVO.getScheduleType());
        }
        if(StringUtils.isNotBlank(pageReqVO.getCreator())){
            params.put("creator",pageReqVO.getCreator());
        }
        if(StringUtils.isNotBlank(pageReqVO.getCompanyName())){
            params.put("companyName",pageReqVO.getCompanyName());
        }
        mpPage.setRecords(praxisEntryInfoMapper.getEntryInfoPage(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    @Override
    public PageResult<PraxisEntryStudentPageRespVO> getEntryInfoPageByProjectId(PraxisEntryStudentPageReqVO pageReqVO) {
        // MyBatis Plus 查询
        IPage<PraxisEntryStudentPageRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        params.put("projectId",pageReqVO.getProjectId());
        params.put("scheduleType",pageReqVO.getScheduleType());
        if(null!=pageReqVO.getLookStatus()){
            params.put("lookStatus",pageReqVO.getLookStatus());
        }
        if(null!=pageReqVO.getCheckStatus()){
            params.put("checkStatus",pageReqVO.getCheckStatus());
        }
        if(StringUtils.isNotBlank(pageReqVO.getTeamName())){
            params.put("teamName",pageReqVO.getTeamName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getStudentName())){
            params.put("studentName",pageReqVO.getStudentName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getSchoolName())){
            params.put("schoolName",pageReqVO.getSchoolName());
        }
        mpPage.setRecords(praxisEntryInfoMapper.getEntryInfoPageByProjectId(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    @Override
    public List<PraxisEntryStudentPageRespVO> getEntryInfoPageByProjectList(PraxisEntryStudentExcelReqVO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("projectId",pageReqVO.getProjectId());
        params.put("scheduleType",pageReqVO.getScheduleType());
        if(null!=pageReqVO.getLookStatus()){
            params.put("lookStatus",pageReqVO.getLookStatus());
        }
        if(null!=pageReqVO.getCheckStatus()){
            params.put("checkStatus",pageReqVO.getCheckStatus());
        }
        if(StringUtils.isNotBlank(pageReqVO.getTeamName())){
            params.put("teamName",pageReqVO.getTeamName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getStudentName())){
            params.put("studentName",pageReqVO.getStudentName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getSchoolName())){
            params.put("schoolName",pageReqVO.getSchoolName());
        }
        return praxisEntryInfoMapper.getEntryInfoPageByProjectList(  params);
    }

    @Override
    public void uploadAnnex(PraxisProjectSourceUpdateVO updateVO) {
        Long num= praxisEntryInfoMapper.getScheduleByEntryId(updateVO.getEntryId(),1);
        if(null==num || num==0){
            throw exception(PRAXIS_PROJECT_SCHEDULE_CLOSE_END);
        }
        praxisEntryInfoMapper.uploadAnnex(updateVO.getEntryId(), updateVO.getAnnexName(),updateVO.getAnnexUrl()
                ,SecurityFrameworkUtils.getLoginUser().getUsername());
    }

    @Override
    public void updateRateScore(PraxisProjectSourceUpdateVO updateVO) {
        Long num= praxisEntryInfoMapper.getScheduleByEntryId(updateVO.getEntryId(),2);
        if(null==num || num==0){
            throw exception(PRAXIS_PROJECT_SCHEDULE_END);
        }
        praxisEntryInfoMapper.updateRateScore(updateVO.getEntryId(), updateVO.getRateScore()
                ,SecurityFrameworkUtils.getLoginUser().getUsername());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @TenantIgnore
    public void batchUpdateStatus(PraxisProjectUpdateVO updateVO) {
        List<PraxisEntryInfoBaseVO> list = praxisEntryInfoMapper.getEntryInfoById(updateVO.getIds());
        //类型;1:入选;2:撤销
        String username = SecurityFrameworkUtils.getLoginUser().getUsername();
        if(CollectionUtils.isNotEmpty(list)){
            PraxisEntryInfoBaseVO firstEntInfo = list.stream().findFirst().orElse(null);
            Integer scheduleType=firstEntInfo.getScheduleType();
            Integer nextScheduleType=NumberUtils.getInteger(firstEntInfo.getNextScheduleType(),scheduleType+1) ;
            Long projectId=firstEntInfo.getProjectId();
            PraxisProjectScheduleVO schedule = praxisEntryInfoMapper.getScheduleByProjectId(projectId, scheduleType);
            if(null==schedule){
                ErrorCode PRAXIS_PROJECT_ENTRY_EXIST1= new ErrorCode(1004001034,  getScheduleTypeName(scheduleType)+"不存在,请先添加赛程");
                throw exception(PRAXIS_PROJECT_ENTRY_EXIST1);
            }
            if(new Date().before(schedule.getStartTime()) || new Date().after(schedule.getEndTime())){
                throw exception(PRAXIS_PROJECT_SCHEDULE_END);
            }
            Integer isSendEmail = NumberUtils.getInteger(updateVO.getIsSendEmail(),0);
            if(updateVO.getType()==0){
                List<Long> nextIds = list.stream().filter(m -> (null != m.getNextEntryId())).map(m -> m.getNextEntryId()).collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(nextIds)){
                    praxisEntryInfoMapper.deleteEntryInfoById(nextIds);
                }
                praxisEntryChosenMapper.deleteEntryChosenById(updateVO.getIds());
            }else if(updateVO.getType()==1){
                if(4==scheduleType){
                    if(StringUtils.isBlank(updateVO.getPrizeName()) ||null==updateVO.getPrizeCeremony() ||null==updateVO.getPrizeType()){
                        throw exception(PRAXIS_PROJECT_ENTRY_NOTNULL);
                    }
                }
                list.stream().forEach(m -> {
                    if(null!=m.getCheckStatus() && 1==m.getCheckStatus()){
                        ErrorCode PRAXIS_PROJECT_ENTRY_EXIST1= new ErrorCode(1004001029, m.getTeamName()+"已入选,不能重复添加");
                        throw exception(PRAXIS_PROJECT_ENTRY_EXIST1);
                    }
                    if (nextScheduleType < 5) {
                        Long aLong = praxisEntryInfoMapper.selectCount(new QueryWrapper<PraxisEntryInfoDO>().eq("project_id", m.getProjectId())
                                .eq("schedule_type", nextScheduleType).eq("student_id", m.getStudentId()).eq("deleted", 0));
                        if (null != aLong && aLong > 0) {
                            ErrorCode PRAXIS_PROJECT_ENTRY_EXIST1 = new ErrorCode(1004001032, m.getTeamName() + "已入选,不能重复添加");
                            throw exception(PRAXIS_PROJECT_ENTRY_EXIST1);
                        }
                    }
                });

                Date date = new Date();
                list.stream().forEach(m->{
                    PraxisEntryChosenDO c=new PraxisEntryChosenDO();
                    c.setEntryId(m.getId());
                    c.setIsSendEmail(isSendEmail);
                    c.setOtherNotes(updateVO.getOtherNotes());
                    c.setLinkMobile(updateVO.getLinkMobile());
                    c.setLinkName(updateVO.getLinkName());
                    c.setCreateTime(date);
                    c.setCreator(username);
                    c.setUpdater(username);
                    c.setUpdateTime(date);
                    if(scheduleType<4){
                        PraxisEntryInfoDO e=new PraxisEntryInfoDO();
                        BeanUtils.copyProperties(m,e);
                        e.setId(null);
                        e.setLookStatus(1);
                        e.setScheduleType(nextScheduleType);
                        e.setEntryStatus(2);
                        e.setAnnexUrl(null);
                        e.setAnnexName(null);
                        e.setRateScore(null);
                        e.setCreateTime(date);
                        e.setUpdateTime(date);
                        e.setCreator(username);
                        e.setUpdater(username);
                        praxisEntryInfoMapper.insert(e);
                    }else{
                        c.setPrizeCeremony(updateVO.getPrizeCeremony());
                        c.setPrizeName(updateVO.getPrizeName());
                        c.setPrizeType(updateVO.getPrizeType());
                    }
                    praxisEntryChosenMapper.insert(c);
                });
                if(1==isSendEmail){
                    PraxisProjectScheduleVO scheduleVO =null;
                    if(5!=nextScheduleType){
                        scheduleVO = praxisEntryInfoMapper.getScheduleByProjectId(firstEntInfo.getProjectId(), nextScheduleType);
                        if(null==scheduleVO){
                            scheduleVO=new PraxisProjectScheduleVO();
                        }
                    }
                    List<Long> firstIds = list.stream().filter(m -> (null != m.getFirstEntryId())).map(m -> m.getFirstEntryId()).collect(Collectors.toList());
                    List<PraxisEntryEmailInfoVO> sList = praxisEntryInfoMapper.getEntryStudentListByIds(firstIds);
                    if(CollectionUtils.isNotEmpty(sList)){
                        for (PraxisEntryEmailInfoVO m : sList) {
                            if(StringUtils.isBlank(m.getEmail())){
                                continue;
                            }
                            m.setScheduleType(nextScheduleType);
                            m.setLinkMobile(updateVO.getLinkMobile());
                            m.setLinkName(updateVO.getLinkName());
                            m.setOtherNotes(updateVO.getOtherNotes());
                            if(4!=scheduleType){
                                m.setClosingDate(scheduleVO.getClosingDate());
                                m.setStartTime(scheduleVO.getStartTime());
                                m.setEndTime(scheduleVO.getEndTime());
                            }else{
                                m.setPrizeCeremony(updateVO.getPrizeCeremony());
                                m.setPrizeName(updateVO.getPrizeName());
                                m.setPrizeType(updateVO.getPrizeType());
                            }
                            sendHtmlMail(m);
                        }
                    }
                }
            }
            praxisEntryInfoMapper.updateCheckStatus(updateVO.getIds(),username,updateVO.getType());
        }
    }

    public String getScheduleTypeName(Integer scheduleType){
        String scheduleTypeName;
        switch (scheduleType){
            case 1:
                scheduleTypeName="遴选";
                break;
            case 2:
                scheduleTypeName="初赛";
                break;
            case 3:
                scheduleTypeName="复赛";
                break;
            case 4:
                scheduleTypeName="决赛";
                break;
            default:
                scheduleTypeName="奖项";
        }
        return scheduleTypeName;
    }

    @Async
    public void sendHtmlMail(PraxisEntryEmailInfoVO entryVO){
        EmailInfo emailInfo=new EmailInfo();
        String scheduleTypeName=getScheduleTypeName(entryVO.getScheduleType());
        emailInfo.setToUser(entryVO.getEmail());
        String companyName=StrUtils.toStr(entryVO.getCompanyName());
        if(StringUtils.isNotBlank(companyName)){
            companyName+="-";
        }
        emailInfo.setEnvironment(active);
        StringBuffer str=new StringBuffer();
        str.append("<!DOCTYPE html><html><head><meta charset='UTF-8'></head><body>");
        if(5!=entryVO.getScheduleType()){
            emailInfo.setSubject("【数据学徒】"+companyName+StrUtils.toStr(entryVO.getProjectTitle())+"-"+StrUtils.toStr(entryVO.getTeamName())+"-"+scheduleTypeName+"入选通知");
            str.append("<p >您好，我们很高兴的通知您已入选 "+StrUtils.toStr(entryVO.getProjectTitle())+"-"+scheduleTypeName+"。具体安排如邮件下方，请于截止日期前上传"+DateUtils.format(entryVO.getClosingDate(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"作品!</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>比赛阶段:"+scheduleTypeName+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>比赛时间:"+DateUtils.format(entryVO.getStartTime(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"至"+DateUtils.format(entryVO.getEndTime(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>作品截止上传时间:"+DateUtils.format(entryVO.getClosingDate(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>其他:"+StrUtils.toStr(entryVO.getOtherNotes())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系人:"+StrUtils.toStr(entryVO.getLinkName())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系方式:"+StrUtils.toStr(entryVO.getLinkMobile())+"</p>");
        }else{
            //1:线上颁奖;2:线下颁奖
            String prizeTypeName="线上颁奖";
            if(2==entryVO.getPrizeType()){
                prizeTypeName="线下颁奖";
            }
            emailInfo.setSubject("【数据学徒】"+companyName+StrUtils.toStr(entryVO.getProjectTitle())+"-"+StrUtils.toStr(entryVO.getTeamName())+"-"+scheduleTypeName+"获奖通知");
            str.append("<p>您好，我们很高兴的通知您已获得"+StrUtils.toStr(entryVO.getProjectTitle())+"奖励。具体颁奖安排如邮件下方!</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>奖项:"+entryVO.getPrizeName()+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>颁奖典礼:"+DateUtils.format(entryVO.getPrizeCeremony() ,DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) +"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>颁奖类型:"+prizeTypeName+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>其他:"+StrUtils.toStr(entryVO.getOtherNotes())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系人:"+StrUtils.toStr(entryVO.getLinkName())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系方式:"+StrUtils.toStr(entryVO.getLinkMobile())+"</p>");
        }
        str.append("<p style='text-align:right; padding-right: 20px;'> <img  width='200px' src='https://demo-oss.oss-cn-beijing.aliyuncs.com/jpg/9fad169ed78a492080a3800a41d97b68.jpg'/></p>");
        str.append("<p style='text-align:right; padding-right: 20px;'>电话：0755-23372612/0755-23372649</p>");
        str.append("<p style='text-align:right; padding-right: 20px;'>contact@datarer.com</p>");
        str.append("<p style='text-align:right; padding-right: 20px;'>www.datarer.com</p>");
        str.append("</body></html>");
        emailInfo.setContent(str.toString());
        threadPoolTaskExecutor.execute(()->{
            HttpUtils.doPost("http://127.0.0.1:8085/demo/task/sendMail",JSONObject.toJSONString(emailInfo));
        });
    }


    @Override
    public List<PraxisEntryStudentVO> getEntryStudentList(Long entryId) {
        return praxisEntryInfoMapper.getEntryStudentList(entryId);
    }

    @Override
    public PraxisEntryInfoBaseVO getEntryInfoById(Long id) {
        List<PraxisEntryInfoBaseVO> list = praxisEntryInfoMapper.getEntryInfoById(Arrays.asList(id));
        PraxisEntryInfoBaseVO vo= CollectionUtils.isNotEmpty(list)?list.get(0) : null;
        if(null!=vo && 1==vo.getLookStatus()){
            PraxisEntryInfoDO entryInfoDO=new PraxisEntryInfoDO();
            entryInfoDO.setId(id);
            entryInfoDO.setLookStatus(2);
            praxisEntryInfoMapper.updateById(entryInfoDO);
        }
        return vo;
    }
}
